#include "BMP_struct.h"


void readFileHeader(FILE *F, BMPFILEHEADER *H)
{
/*F é o arquivo Bitmap que deve ter sido “lido” do disco*/

    fread(&H->Type,sizeof(char),2,F);
    fread(&H->Size,sizeof(unsigned int),1,F);
    fread(&H->Reserved1,sizeof(unsigned short),1,F);
    fread(&H->Reserved2,sizeof(unsigned short),1,F);
    fread(&H->OffBits,sizeof(unsigned int),1,F);
}

void readInfoHeader(FILE *F,BMPINFOHEADER *IH)
{
    fread(&IH->biSize,sizeof(unsigned  int),1,F);
    fread(&IH->biWidth,sizeof(int),1,F);
    fread(&IH->biHeight,sizeof(int),1,F);
    fread(&IH->biPlanes,sizeof(unsigned short int),1,F);
    fread(&IH->biBitCount,sizeof(unsigned short int),1,F);
    fread(&IH->biCompression,sizeof(unsigned int),1,F);
    fread(&IH->biSizeImage,sizeof(unsigned int),1,F);
    fread(&IH->biXPelsPerMeter,sizeof(int),1,F);
    fread(&IH->biYPelsPerMeter,sizeof(int),1,F);
    fread(&IH->biClrUsed,sizeof(unsigned int),1,F);
    fread(&IH->biClrImportant,sizeof(unsigned int),1,F);
}

void readContenImage(FILE *F, CONTENTIMAGE *C) //le um pixel da imagem
{
    fread(&C->Blue,sizeof(char),1,F);
    fread(&C->Green,sizeof(char),1,F);
    fread(&C->Red,sizeof(char),1,F);
    //fread(&C->Reserved,sizeof(unsigned char),1,F); //acho que nao precisa disso! vc vai ler 4 bytes por pixel
}

void calcDiff(CONTENTIMAGE *C,char *container,int length)
{
    int i;
    int previous[3];
    for(i=0;i<3;i++)
    {
        previous[i]=0;
    }

    container = (char*)malloc(sizeof(char)*length);

    for(i=0;i<(length)/3;i++)
    {
       container[i] =   C[i].Blue - previous[0];
       container[i+1] = C[i].Green - previous[1] ;
       container[i+2]= C[i].Red - previous[2];

       container[0]= C[i].Blue;
       container[1]= C[i].Green;
       container[2] = C[i].Red;
    }
}

void writeFile(FILE *F,BMPFILEHEADER *H,BMPINFOHEADER *IH,FileContent *fileContent, int leafNumber, HuffTree* huffTree)
{
    //escreve cabecalho huffman
    unsigned char number = leafNumber;
    unsigned char huffCodeTamC, huffCodeC, iC;
    int i, huffCodeTam, huffCode;
    Node* no = getStart(fileContent);
    int totalBits;
    unsigned char *buffer, *bufferHuff, *bufferNum;

    fwrite(&number, sizeof(unsigned char), 1, F); //grava numero de codigos huffman

    for(i=1; i<= 8; i++) //i = tamanho em bits correspondente
    {
        huffCode = getCodeHuff(huffTree,i, &huffCodeTam);

        if(huffCode > 255) //se nao existe codigo huffman
        {
            huffCodeC = huffCode;
            huffCodeTamC = huffCodeTam;
            iC = i;

            fwrite(&huffCodeTamC, sizeof(unsigned char), 1, F); //grava cabecalho huffman
            fwrite(&huffCodeC, sizeof(unsigned char), 1, F);
            fwrite(&iC, sizeof(unsigned char), 1, F);
        }
    }

    //grava cabecalho Header
    fwrite(&H->Type,sizeof (char),2,F);
    fwrite(&H->Size,sizeof (unsigned int),1,F);
    fwrite(&H->Reserved1,sizeof (unsigned short int),1,F);
    fwrite(&H->Reserved2,sizeof (unsigned short int),1,F);
    fwrite(&H->OffBits,sizeof (unsigned int),1,F);

    //grava cabecalho header info
    fwrite(&IH->biSize,sizeof(unsigned  int),1,F);
    fwrite(&IH->biWidth,sizeof(int),1,F);
    fwrite(&IH->biHeight,sizeof(int),1,F);
    fwrite(&IH->biPlanes,sizeof(unsigned short int),1,F);
    fwrite(&IH->biBitCount,sizeof(unsigned short int),1,F);
    fwrite(&IH->biCompression,sizeof(unsigned int),1,F);
    fwrite(&IH->biSizeImage,sizeof(unsigned int),1,F);
    fwrite(&IH->biXPelsPerMeter,sizeof(int),1,F);
    fwrite(&IH->biYPelsPerMeter,sizeof(int),1,F);
    fwrite(&IH->biClrUsed,sizeof(unsigned int),1,F);
    fwrite(&IH->biClrImportant,sizeof(unsigned int),1,F);

    //grava arquivo comprimido
    no = getStart(fileContent);
    totalBits = 0;
    int aux = 0;
    while(no != 0) //conta quantos bits serao necessarios
    {
        totalBits += no->huffCodeTam + no->numBits;
        no = no->next;
        aux++;
    }
    printf("TAMANHO-- %d ###############\n",aux);
    printf("saiu");
    buffer = (unsigned char*) malloc((totalBits+5)*sizeof(unsigned char));
    buffer[0] = '\0';
    bufferHuff = (unsigned char*) malloc(sizeof(unsigned char)*10);
    bufferHuff[0] = '\0';
    bufferNum = (unsigned char*) malloc (sizeof(unsigned char)*10);
    bufferNum[0] = '\0';

    no= getStart(fileContent);
    aux =0;
    while(no != 0)
    {
        bufferHuff = (unsigned char *)intToChar(no->huffCode, no->huffCodeTam);
		bufferNum = (unsigned char *)intToChar(no->bits, no->numBits);

		strcat((char *)buffer,(char *) bufferHuff);
		strcat((char *)buffer,(char *) bufferNum);
        no = no->next;
        aux++;
        printf("\n%d",aux);
    }

    int count = 0;
	int bytecont = 0;
	int binNumber = 0;

	while(count<=totalBits || bytecont!=0)
    {
        if(count==totalBits && bytecont!=0)
        {
            for (i=31-bytecont; i>=0; i--)
            {
                binNumber = (binNumber << 1);
            }
            bytecont = 0;
            count ++;
            fwrite (&binNumber, sizeof(int), 1, F);
        }
        if(count<=totalBits)
        {

            for (i = 0; i<totalBits; i++)
            {
                if (buffer[i]=='0')
                {
                    binNumber = (binNumber << 1);
                }
                else if (buffer[i]=='1')
                {
                    binNumber = (binNumber << 1);
                    binNumber = binNumber | 1;
                }
                bytecont ++;
                count++;
                if (bytecont == 31)
                {
                    bytecont = 0;
                    fwrite (&binNumber, sizeof(int), 1, F);
                    binNumber = 0;
                }
            }
        }
    }

}

void writeFile_d(FILE *F,BMPFILEHEADER *H,BMPINFOHEADER *IH,FileContent *fileContent,int length)
{

    fwrite(&H->Type,sizeof (char),2,F);
    fwrite(&H->Size,sizeof (unsigned int),1,F);
    fwrite(&H->Reserved1,sizeof (unsigned short int),1,F);
    fwrite(&H->Reserved2,sizeof (unsigned short int),1,F);
    fwrite(&H->OffBits,sizeof (unsigned int),1,F);

    fwrite(&IH->biSize,sizeof(unsigned  int),1,F);
    fwrite(&IH->biWidth,sizeof(int),1,F);
    fwrite(&IH->biHeight,sizeof(int),1,F);
    fwrite(&IH->biPlanes,sizeof(unsigned short int),1,F);
    fwrite(&IH->biBitCount,sizeof(unsigned short int),1,F);
    fwrite(&IH->biCompression,sizeof(unsigned int),1,F);
    fwrite(&IH->biSizeImage,sizeof(unsigned int),1,F);
    fwrite(&IH->biXPelsPerMeter,sizeof(int),1,F);
    fwrite(&IH->biYPelsPerMeter,sizeof(int),1,F);
    fwrite(&IH->biClrUsed,sizeof(unsigned int),1,F);
    fwrite(&IH->biClrImportant,sizeof(unsigned int),1,F);

    Node *pb = getStart(fileContent);
    fwrite(&pb->valueDec,sizeof(char),1,F);
    while(pb != fileContent->end){
//         fwrite(&pb->valueDec,sizeof(&pb->valueDec),1,F
        pb = pb->next;
         fwrite(&pb->valueDec,sizeof(char),1,F);
         }
    printf("%d\n",length);
    printf("Arquivo Criado\n");
}

void writeFile_emanuel(FILE *F,BMPFILEHEADER *H,BMPINFOHEADER *IH,FileContent *fileContent, int leafNumber, HuffTree* huffTree)
{
    //escreve cabecalho huffman
    unsigned char number = leafNumber;
    unsigned char huffCodeTamC, huffCodeC, iC;
    int i, huffCodeTam, huffCode;
    Node* no = getStart(fileContent);
    unsigned char *buffer, *bufferHuff, *bufferNum;

    int totalBits;

    fwrite(&number, sizeof(unsigned char), 1, F); //grava numero de codigos huffman
    printf("%d",number);
    for(i=1; i<= 8; i++) //i = tamanho em bits correspondente
    {
        huffCode = getCodeHuff(huffTree,i, &huffCodeTam);

        if(huffCode < 255) //se nao existe codigo huffman
        {
            huffCodeC = huffCode;
            huffCodeTamC = huffCodeTam;
            iC = i;
            fwrite(&huffCodeTamC, sizeof(unsigned char), 1, F); //grava cabecalho huffman
            fwrite(&huffCodeC, sizeof(unsigned char), 1, F);
            fwrite(&iC, sizeof(unsigned char), 1, F);
        }
    }

    //grava cabecalho Header
    fwrite(&H->Type,sizeof (char),2,F);
    fwrite(&H->Size,sizeof (unsigned int),1,F);
    fwrite(&H->Reserved1,sizeof (unsigned short int),1,F);
    fwrite(&H->Reserved2,sizeof (unsigned short int),1,F);
    fwrite(&H->OffBits,sizeof (unsigned int),1,F);

    //grava cabecalho header info
    fwrite(&IH->biSize,sizeof(unsigned  int),1,F);
    fwrite(&IH->biWidth,sizeof(int),1,F);
    fwrite(&IH->biHeight,sizeof(int),1,F);
    fwrite(&IH->biPlanes,sizeof(unsigned short int),1,F);
    fwrite(&IH->biBitCount,sizeof(unsigned short int),1,F);
    fwrite(&IH->biCompression,sizeof(unsigned int),1,F);
    fwrite(&IH->biSizeImage,sizeof(unsigned int),1,F);
    fwrite(&IH->biXPelsPerMeter,sizeof(int),1,F);
    fwrite(&IH->biYPelsPerMeter,sizeof(int),1,F);
    fwrite(&IH->biClrUsed,sizeof(unsigned int),1,F);
    fwrite(&IH->biClrImportant,sizeof(unsigned int),1,F);

      while(no != 0) //conta quantos bits serao necessarios
    {
        totalBits += no->huffCodeTam + no->numBits;
        no = no->next;
    }

    //grava arquivo comprimido
    no = getStart(fileContent);

    buffer = (unsigned char*) malloc((32)*sizeof(char));
    buffer[0] = '\0';
    bufferHuff = (unsigned char*) malloc(sizeof(char)*10);
    bufferHuff[0] = '\0';
    bufferNum = (unsigned char*) malloc (sizeof(char)*10);
    bufferNum[0] = '\0';

    int j=0;
    while(no != 0)
    {
        bufferHuff =(unsigned char *)intToChar(no->huffCode,no->huffCodeTam);
		bufferNum =(unsigned char *)intToChar(no->bits, no->numBits);

        for (i=0; i<no->huffCodeTam; i++)
        {
            buffer[j] = bufferHuff[i];
            j++;
            if(j == 32)
            {
                preencheArq(F, buffer, j);
                buffer[0] = '\0';
                j = 0;
            }
        }

        for (i=0; i<no->numBits; i++)
        {
            buffer[j] = bufferNum[i];
            j++;
            if(j == 32)
            {
                preencheArq(F, buffer, j);
                buffer[0] = '\0';
                j = 0;
            }
        }
        no = no->next;
        if (no == 0 && j != 0)
        {
            preencheArq(F, buffer, j);
            buffer[0] = '\0';
            j = 0;
        }
    }

}

void preencheArq(FILE *F, unsigned char* buffer, int totalBits)
{
    int i = 0;
	int binNumber = 0;

    if(totalBits == 32)
    {
        for (i = 0; i<totalBits; i++)
        {
            if (buffer[i]=='0')
            {
                binNumber = (binNumber << 1);
            }
            else if (buffer[i]=='1')
            {
                binNumber = (binNumber << 1);
                binNumber = binNumber | 1;
            }
        }
        fwrite (&binNumber, sizeof(int), 1, F);
        binNumber = 0;
    }
    else
    {
        printf("Entrou ELSE");
        for (i=31-totalBits; i>=0; i--)
        {
            binNumber = (binNumber << 1);
        }
        fwrite (&binNumber, sizeof(int), 1, F);
    }
}


void readContenImage_c(FILE *F, CONTENTIMAGE *C) //le um pixel da imagem
{
    fread(&C->Blue,sizeof(char),1,F);
    fread(&C->Green,sizeof(char),1,F);
    fread(&C->Red,sizeof(char),1,F);
    //fread(&C->Reserved,sizeof(unsigned char),1,F); //acho que nao precisa disso! vc vai ler 4 bytes por pixel
}
//void readFile(FileContent *fileContent,int length)
//{
//    Node *pb = getStart(fileContent);
//    while(pb->next){
//
//         fread(&pb->valueDec,sizeof(&pb->valueDec),1,F);
//         pb = pb->next;
//         }
//
//
//
//
//    printf("%d\n",length);
//    printf("Arquivo Criado\n");
//}
//
